﻿using Newtonsoft.Json.Serialization;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net.Http.Formatting;
using System.Reflection;
using System.Web.Http;
using System.Web.Http.Cors;
using WebApiThrottle;
using XieCan.AspMVC.AutofacApi;

namespace XieCan.AspMVC.WebApi
{
#pragma warning disable CS1591 // 缺少对公共可见类型或成员的 XML 注释
    public static class WebApiConfig
#pragma warning restore CS1591 // 缺少对公共可见类型或成员的 XML 注释
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API 配置和服务 
            //跨域配置
            var allowedMethods = ConfigurationManager.AppSettings["cors:allowedMethods"] ?? "*";
            var allowedOrigin = ConfigurationManager.AppSettings["cors:allowedOrigin"] ?? "*";
            var allowedHeaders = ConfigurationManager.AppSettings["cors:allowedHeaders"] ?? "*";
            var geduCors = new EnableCorsAttribute(allowedOrigin, allowedHeaders, allowedMethods)
            {
                SupportsCredentials = true
            };
            config.EnableCors(geduCors);

            // 解决json序列化时的循环引用问题
            config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
            // 移除XML序列化器
            config.Formatters.Remove(config.Formatters.XmlFormatter);
            //设置序列化方式为驼峰命名法
            config.Formatters.OfType<JsonMediaTypeFormatter>().First().SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();

            // Web API 路由
            config.MapHttpAttributeRoutes();
            //config.Routes.MapHttpRoute(
            //    name: "DefaultApi",
            //    routeTemplate: "api/{controller}/{id}",
            //    defaults: new { controller = "Swagger", id = RouteParameter.Optional }
            //);
            config.Routes.MapHttpRoute(
                name: "ActionApi",
                routeTemplate: "api/{controller}/{action}/{id}",
                defaults: new { controller = "Swagger", id = RouteParameter.Optional }
            );

            //WebApiConfig 增加
            config.MessageHandlers.Add(new ThrottlingHandler()
            {
                Policy = new ThrottlePolicy(
                    perSecond: 5            //可选参数 每秒限制次数
                                            //, perMinute: 20         //可选参数 每分钟限制次数
                                            //, perHour: 200          //可选参数 每小时限制次数
                                            //, perDay: 1500          //可选参数 每天限制次数
                                            //, perWeek: 3000         //可选参数 每周限制次数
                    )
                {
                    StackBlockedRequests = true, //拒绝的请求累加到WebApiThrottle的计数器里 


                    //******IP限流策略
                    IpThrottling = true,   //该值指示是否启用IP限制
                    IpRules = new Dictionary<string, RateLimits>//针对指定IP单独设置限制
                    {
                        { "::1/10", new RateLimits { PerSecond = 2 } },
                        { "192.168.2.1", new RateLimits { PerMinute = 30, PerHour = 30 * 60, PerDay = 30 * 60 * 24 } }
                    },
                    //添加127.0.0.1到白名单，本地地址不启用限流策略
                    IpWhitelist = new List<string> { "127.0.0.1", "192.168.0.0/24" },


                    //******客户端限流策落
                    ClientThrottling = true, //该值指示是否启用客户端限制
                    ClientRules = new Dictionary<string, RateLimits>//客户端配置区域，如果ip限制也是启动的，那么客户端限制策略会与ip限制策略组合使用。
                    {
                        { "api-client-xiecan-cc", new RateLimits { PerDay = 5000 } }
                    },
                    //白名单中的客户端key不会进行限流。
                    ClientWhitelist = new List<string> { "api-xiecan-cc" },


                    //******端点限流策略
                    EndpointThrottling = true,
                    EndpointRules = new Dictionary<string, RateLimits>
                    {
                        { "api/account/register", new RateLimits { PerSecond = 1, PerMinute = 2, PerHour = 5 } }
                    }
                },
                Repository = new CacheRepository(),
                //QuotaExceededMessage = JsonConvert.SerializeObject(json.msg),
                QuotaExceededContent = (times, per) =>  //违反限流事件
                {
                    //var json = new JsonResult { code = 0, msg = $"超出规定的频率了,{l}{obj}" };
                    return OperateResult<bool>.Failed($"系统检测您当前请求过于频繁，已被限流{{{times}times/{per}}}");
                }
            });

            //为所有ApiController注入Service
            AutofacApiHelper.AppendAssembly(assemblies: typeof(BaseController).Assembly, filter: type => type.BaseType == typeof(BaseController));
            AutofacApiHelper.AppendAssembly(assemblies: Assembly.Load("XieCan.AspMVC.Service"), interfaces: true);
            AutofacApiHelper.RegisterAllTypes(config);
        }
    }
}
